<template>
  <div class="md-page" :class="{'md-priview-page':mdIsPreview}">
    <link rel="stylesheet" href="/jf-ui-public/cdn/editor.md/css/editormd.css">
    <!-- editormd -->
    <!-- <button id="get-md-btn">Get Markdown</button>
    <button id="get-html-btn">Get HTML</button> -->
    <!-- 
    <div id="editor" style="z-index: 10;" readonly v-if="!mdIsPreview"></div>
    <div id="editorPreview" v-if="mdIsPreview" :style="{maxWidth:$superWidth()?'1050px':null,margin:$superWidth()?'0 auto':null}"></div>
     -->
     <BytemdViewer v-if="mdIsPreview" :value="content" :plugins="plugins" class="markdown-component" />
     <Editor v-else :value="content" :plugins="plugins" @change="handleChange" class="markdown-component" :locale="locale === 'zh-CN' ? zh_hans : english"  />

    <div class="editor-toolbar-mark" v-if="isReadonly" :style="{height:markHeight+'px'}"></div>
    <div class="menu-box" :class="[!openMenu && !mdIsPreview && 'hidden-menu-box']">
      <menuList ref="menuListRef" v-if="!mdIsPreview && !isMobile" :isEditor="true" :menuList="menuLists" :show="openMenu" @close="changeMenuStatus" @clickScroll="scrollNode"></menuList>
    </div>
    <el-tooltip :content="$t('message.tooltips.showMenu')" effect="light" placement="right"  v-if="!openMenu && !mdIsPreview && !isMobile">
        <div class="menu-button-box" @click="changeMenuStatus">
            <svg class="menu-icon">
                <use xlink:href="#keowledge-zhankaimulu"></use>
            </svg>
        </div>
    </el-tooltip>
  </div>
</template>

<script setup lang="ts">
import {
  ref,
  watch ,
  onMounted,
  computed,
  getCurrentInstance,
  onBeforeUnmount,
  nextTick
} from 'vue' 
import type {ComponentInternalInstance} from 'vue'

// import scriptjs from 'scriptjs'
// import initPasteDragImg from './uploadImg'
import { getShareInfo, preview, saveContent  } from '@/api/common'
import { saveVersion } from '@/api/version'
import useUserInfoStore from '@/store/userInfo'
import { useHookI18n } from '@/hooks/i18n'
const { locale,$t } = useHookI18n()
const userStore = useUserInfoStore()
import useSocketStore from '@/store/socket'
const socketStore = useSocketStore()
import menuList from '@/views/common/menuList.vue'

import gfm from '@bytemd/plugin-gfm'
import 'bytemd/dist/index.css'
import zh_hans from 'bytemd/locales/zh_Hans.json'
import english from 'bytemd/locales/en.json'
import { Editor, Viewer as BytemdViewer } from '@bytemd/vue-next'

const plugins = [gfm()]

function handleChange(val: string) {
	console.log(val)
    content.value = val
}

const instance: any = getCurrentInstance() as ComponentInternalInstance;
const proxy: any = instance.proxy as any; // 访问 proxy 属性
const emit = defineEmits(["renderFinish","changeUsers","setMenuList","changePrivew",'changeLatelySave'])
const props = defineProps({
  formShare: {
      type: Boolean
    },
    readonly: {
      type: Boolean,
      default: () => {
        return false;
      },
    },
    // 是否开启写作组件
    isWriting:{
      type:Boolean,
      default:false
    },
    versioPreView:{
      type:Boolean,
      default:false
    },
    mdIsPreview:{
      type:Boolean,
      default:false
    },
    height: {
      type: String,
      required: false,
      default: 'calc(100vh - 48px)'
    },
    id: {
      type: String,
      default: () => {
        return ''
      },
    },
    docInfo:{
      type:Object,
      default:()=>{return {}}
    }
})
const editor = ref({})
const content = ref('')
const isReadonly = ref(false)
const markHeight = ref(39)
const originUsers = ref<any[]>([]) // 起始协同人员列表
const menuLists = ref([]) //目录列表
const originmenuList = ref([]) //原始数据
const openMenu = ref(false)
const cliclMenuScroll = ref(false)
const menuListRef = ref()
const getWsMsg = computed<any>(()=>{
  return socketStore.socketMsg
}) 
const isMobile = computed(()=>{
  let flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)
  return flag;
}) 

onMounted(()=>{
  if (!props.mdIsPreview && userStore.access_token) {
    socketStore.INIT(props.id)
  }
  setTimeout(() => {
    initMd()
  }, 100)
})
onBeforeUnmount(()=>{
  document.querySelector('.CodeMirror-scroll')?.removeEventListener('scroll',openScrollListener)
})

watch(()=>getWsMsg.value,(newVal)=>{
  if(!props.readonly) {
    // 实时消息
    if(newVal.command == 26 && newVal.data) {
      if(userStore.userInfo.id != newVal.data.from) {
        let ctt = newVal.data.content
        switch (ctt.type) {
          case "changeVersion":
            proxy.$confirm($t('message.confirm.versionBack'), $t('message.message.contentChanged'), {
              confirmButtonText: $t('message.buttons.submit'),
              cancelButtonText: $t('message.buttons.cancal'),
              type: 'warning'
            }).then(() => {
              handleSave()
              // editor.value.setMarkdown(content.data)
              content.value = ctt.data
            }).catch(() => {
              content.value = ctt.data
              // editor.value.setMarkdown(content.data)
            });
            break
          default:
            break;
        }
      }
    }
    // 初始获取当前组的人员列表
    if(newVal.command == 32 && newVal.data) {
      for(let u in newVal.data.users) {
        let ix = hasInGroup(newVal.data.users[u].userId)
        if(ix == -1) {
          if(newVal.data.users[u].status == 'online') {
            originUsers.value.push(newVal.data.users[u])
          }
        }else{
          if(newVal.data.users[u].status != 'online') {
            originUsers.value.splice(ix, 1)
          }
        }
      }
      emit('changeUsers', originUsers.value)
    }
    // 新人加入组更新人员列表
    if(newVal.command == 9 && newVal.data && newVal.data.user) {
      let index = hasInGroup(newVal.data.user.userId)
      if(index == -1 && newVal.data.user.status == 'online') {
        originUsers.value.push(newVal.data.user)
      }else{
        if(index > -1 && newVal.data.user.status == 'offline') {
          originUsers.value.splice(index, 1)
        }
      }
      emit('changeUsers', originUsers.value)
    }
    // 人员退出群组
    if(newVal.command == 10 && newVal.data && newVal.data.user) {
      let index = hasInGroup(newVal.data.user.userId)
      if(index > -1) {
        originUsers.value.splice(index, 1)
      }
      emit('changeUsers', originUsers.value)
    }
  }
})

watch(()=>props.id,()=>{
  initMd()
})
// watch(()=>props.versioPreView,(newVal,oldVal)=>{
//   if(newVal!=oldVal){
//     if(newVal == true){
//       this.$refs.version.getVersionAll()
//     }
//   }
// },{deep:true})

// 判断人员是否已加入群组
function hasInGroup (userId: any) {
  let index: any = -1
  for(let o in originUsers.value) {
    if(originUsers.value[o].userId == userId) {
      index = o
    }
  }
  return index
}
function initMd(){
  let fun: any = preview
  if(!props.mdIsPreview){
    const businessId = props.id + '-knowledge-ui'
    const userId = userStore.userInfo.id
    firstInit(businessId,userId)
  }
  if(props.formShare) {
    fun = getShareInfo
  }
  fun(props.id,{
    time:new Date().getTime()
  }).then((res: { data: { code: number; data: { content: string } } })=>{
    if (res.data.code == 0 && res.data.data) {
      if (res.data.data.content && res.data.data.content.startsWith("{")) {
        let resData = JSON.parse(res.data.data.content).content;
        if (resData && resData.startsWith("[")  && resData.endsWith("]")) {
          content.value = JSON.parse(resData);
        } else if (resData && resData.startsWith("{")  && resData.endsWith("}")) {
          content.value = JSON.parse(resData);
        } else {
          content.value = resData;
        }
      } else {
        content.value = "";
      }
      initEditor()
    }
  }).finally(()=>{
    emit('renderFinish')
  })
}
function initEditor() {
  // (async() => {
  //   await fetchScript('/jf-ui-public/cdn/editor.md/editormd.js')
  //   if(locale.value.indexOf('zh')==-1){
  //     await fetchScript('/jf-ui-public/cdn/editor.md/languages/en.js')
  //   }
    
  //   // // await this.fetchScript('/jf-ui-public/cdn/editor.md/editormd.amd.js')
  //   if(props.mdIsPreview){
  //     await fetchScript('/jf-ui-public/cdn/editor.md/lib/marked.min.js')
  //     await fetchScript('/jf-ui-public/cdn/editor.md/lib/prettify.min.js')
  //     await fetchScript('/jf-ui-public/cdn/editor.md/lib/raphael.min.js')
  //     await fetchScript('/jf-ui-public/cdn/editor.md/lib/sequence-diagram.min.js')
  //     await fetchScript('/jf-ui-public/cdn/editor.md/lib/flowchart.min.js')
  //   }
  //   nextTick(() => {
  //     // 内容 
  //     if(!props.mdIsPreview){
  //       editor.value = window.editormd('editor', {
  //         path: '/jf-ui-public/cdn/editor.md/lib/',
  //         placeholder:$t('message.placeholder.markdown'),
  //         height: props.height,
  //         emoji: true,
  //         // 工具栏
  //         toolbarIcons:['undo','redo','|','bold','del','italic','quote','ucwords','uppercase','lowercase','|','h1','h2','h3','h4','h5','h6','|','list-ul','list-ol','hr',
  //         '|','link','reference-link','image','code','preformatted-text','code-block','table','datetime','emoji','html-entities','pagebreak','|','goto-line','watch',
  //         'preview','fullscreen','clear','search','help'],
  //         // 开启图片上传，图片上传重写了的
  //         saveHTMLToTextarea: true,
  //         // 可分区域定制样式主题
  //         theme        : "default",
  //         editorTheme  : "default",
  //         previewTheme : "default",
  //         imageUpload: true,
  //         sequenceDiagram : true,
  //         imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp","ico"],
  //         lang:{
  //           name: locale.value.indexOf('zh')!=-1?"zh-cn":'en',
  //         },
  //         reqData:{

  //         },
  //         headers:{
  //           businessId:props.docInfo.id,
  //           Authorization: 'Bearer ' + userStore.access_token
  //         },
  //         //需在服务端定义接口
  //         // 这里需要考虑返回值，所以封装了一层
  //         imageUploadURL: '#',
  //         custImageUploadUrl:'/mgr/jvs-auth/upload/jvs-public',
  //         htmlDecode: true, // 识别html标签
  //         onpreviewing : function() {
  //           // 这里只是预览
  //         },
  //         onpreviewed : function() {
  //           // 这里是编辑加预览
  //         },
  //         // 监听更新，更新父组件值
  //         onchange: function() {
  //           // console.log("111")
  //           // 获取当前页面的的光标位置
  //           createMenuList(editor.value.markdownToC)
  //           originmenuList.value = editor.value.markdownToC
  //         },
  //         // 退出全屏
  //         onfullscreen: function() {
  //           // 原生JS修改层级
  //           var editor = document.getElementById('editor')
  //           editor.style['z-index'] = 13
  //         },
  //         // 全屏
  //         onfullscreenExit: function() {
  //           // 原生JS修改层级
  //           var editor = document.getElementById('editor')
  //           editor.style['z-index'] = 10
  //         },
  //         // 大小改变
  //         onresize : function() {
  //           // this.setMarkdown()
  //           markHeight.value = document.getElementsByClassName("editormd-toolbar")[0].clientHeight
  //         },
  //         // 加载完成后再设置内容
  //         onload: function() {
  //           emit('renderFinish')
  //           this.setMarkdown(content.value)
  //           initPasteDragImg(this)
  //           document.querySelector('.CodeMirror-scroll').addEventListener('scroll',openScrollListener)
  //           // let divDom = document.createElement('div')
  //           // divDom.className = ['test-div']
  //           // divDom.id = 'custom-box'
  //           // document.getElementById('editor').appendChild(divDom)
  //         }
  //       })
  //     }else{
  //       document.getElementById('editorPreview').innerHTML = ''
  //       const textareaDom = document.createElement('textarea')
  //       textareaDom.id = 'append-test'
  //       textareaDom.style = 'display:none'
  //       textareaDom.innerHTML = content.value
  //       let originList
  //       if(!isMobile.value){
  //         originList = getMarkDownMenu(content.value)
  //         createMenuList(originList)
  //       }
  //       document.getElementById('editorPreview').append(textareaDom)
  //       editor.value = window.editormd.markdownToHTML("editorPreview", {
  //         // tocm            : true,  
  //         htmlDecode      : "style,script,iframe",  // you can filter tags decode
  //         emoji           : true,
  //         taskList        : true,
  //         tex             : true,  // 默认不解析
  //         sequenceDiagram : true,  // 默认不解析
  //       });
  //       emit('setMenuList',menuLists.value,originList)
  //       emit('renderFinish')
  //     }
  //     // const vm = this
  //     // 监听，改变父组件的值
  //     // editor.on('change', function() {
  //     //   vm.$emit('update:modelValue', this.getMarkdown())
  //     // })
  //     // window.editorMd = editor
  //   })
  // })()
}
function openScrollListener(e){
  if(cliclMenuScroll.value) return
  let lastId = ''
  originmenuList.value.forEach((item,index)=>{
    if(document.getElementById(`h${item.level}-${item.slug}`)?.offsetTop-document.querySelector('.CodeMirror-scroll').scrollTop<=14){
      lastId = item.slug
    }
  })
  if(lastId){
    menuListRef.value?.setCurrentKey(lastId)
  }
}
function getMarkDownMenu(val){
  let arr = []
  if(val){
    const lines = val.split('\n')
    let currentLevel = 0
    for(const line of lines){
      const headingMatch = /^#+\s*(.*)/.exec(line);
      if(!headingMatch) continue
      const level = headingMatch[0].replace(/\s/g, '').length-headingMatch[1].replace(/\s/g, '').length
      let text = headingMatch[1]
      text = extractTextFromMarkdownLink(text)
      var escapedText  = text.toLowerCase().replace(/[^\w]+/g, "-");
      arr.push({
        label:text,
        id:escapedText,
        text:text,
        level:level,
        slug:escapedText
      })
    }
    return arr
  }else{
    return arr
  }
}
function extractTextFromMarkdownLink(val){
  // 匹配Markdown链接的正则表达式，全局查找所有链接
  const linkRegexp = /\[(.*?)\]\((.*?)\)/g;

  // 使用replace函数替换所有匹配项，同时保持非链接文本不变
  return val.replace(linkRegexp, '$1');
}
function createMenuList(val){
  menuLists.value = []
  let preNode = '',preItem = null,nextItem = {}
  val.forEach((item,index)=>{
    if(item.level==1){
      preItem = {
        label: item.text,
        value: item.text,
        level:item.level,
        id:item.slug,
        nodeName:`h${item.level}`,
        offsetTop:document.getElementById(`h${item.level}-${item.slug}`)?.offsetTop,
        children:[]
      }
      menuLists.value.push(preItem)
    }else{
      nextItem =  {
        label: item.text,
        value: item.text,
        level:item.level,
        id:item.slug,
        nodeName:`h${item.level}`,
        offsetTop:document.getElementById(`h${item.level}-${item.slug}`)?.offsetTop,
        children:[]
      }
      preNode = 'h' + (item.level - 1)
      findLastPush(preNode,item.level,nextItem,menuLists.value)
    }
  })
}
function findLastPush(preNode,nodeName,nextItem,data){
  let lastData = data[data.length - 1]
  if(lastData?.level === nodeName){
      data.push(nextItem)
  }else if(lastData?.children.length>0){
    findLastPush(preNode,nodeName,nextItem,lastData.children)
  }else{
    if(!lastData || lastData.level>nodeName){
        data.push(nextItem)
    }else{
        lastData?.children.push(nextItem)
    }
  }
}
// function fetchScript(url) {
//   return new Promise((resolve) => {
//     scriptjs(url, () => {
//       resolve()
//     })
//   })
// }
function handleSave(){
  let html = '' // editor.value.getHTML()
  let txt = content.value
  let fun = saveContent
  fun(props.id, { content: txt, contentHtml:html }).then( res => {
    if (res.data.code == 0) {
      proxy.$notify({
        title: $t('message.message.saveSuccess'),
        type: "success",
        position: "bottom-right",
      });
    }
    emit("changeLatelySave",new Date())
  });
}
// function changePrivew(){
//   emit('changePrivew',!props.versioPreView)
// }
// function changeVersionContent(content,type){
//   if(type=='handleVersion'){
//     content.value = JSON.parse(content).content
//     editor.value.setMarkdown(content.value)
//     // 告知其他用户内容已被更改
//     let businessId = props.id + '-knowledge-ui'
//     let userId = userStore.userInfo.id
//     handleSend({
//       cmd: 25,
//       from: userId,
//       businessId: businessId,
//       expire: 60 * 60,
//       content: { type: 'changeVersion', data: content.value  }
//     })
//   }
// }
// 保存版本
function saveVersionF(){
  let viewString = editor.value.getMarkdown()
  let viewStringHtml = editor.value.getHTML()
  saveVersion({
    dcId:props.id,
    content:JSON.stringify({
      content:viewString,
      contentHtml:viewStringHtml
    })
  }).then(res=>{
    if(res.data.code == 0){
      proxy.$notify({
        title: $t('message.message.versionSaveSuccess'),
        type: "success",
        position: "bottom-right",
      });
    }
  })
}
function saveVersionFun(){
  saveVersionF()
}
function firstInit(businessId: string, userId: any) {
  const messageList = {
    cmd: 19,
    messageType: 4,
    userId: userId,
    businessId: businessId
  }
  const joinData = {
    cmd: 25,
    from: userId,
    businessId: businessId,
    expire: 60 * 60
  }
  const groupData = {
    cmd: 31,
    groupId: businessId,
  }
  const joingroup = {
    cmd: 7,
    groupId: businessId,
    groupType: 1,
  }
  handleSend(messageList)
  // 历史协同人员
  handleSend({
    cmd: 19,
    messageType: 4,
    userId: userId,
    businessId: props.id+'-user-list'
  })
  handleSend(joinData)
  handleSend(groupData)
  handleSend(joingroup)
}
function handleSend(data: { cmd: number; messageType?: number; userId?: any; businessId?: string; from?: any; expire?: number; groupId?: string; groupType?: number }) {
  socketStore.SEND_MESSAGE(data)
}
// function handleResize(){
//   editor.value.resize(document.getElementById('editor-content').clientWidth,document.getElementById('editor-content').clientHeight)
// }
// function changeEditStatus(val){
//   nextTick(()=>{
//     isReadonly.value = val
//     if(isReadonly.value){
//       // editor.value.hideToolbar()
//       editor.value.codeEditor.setOption('readOnly','nocursor')
//     }else{
//       // editor.value.showToolbar()
//       editor.value.codeEditor.setOption('readOnly',false)
//     }
//     editor.value.resize(document.getElementById('editor-content').clientWidth,document.getElementById('editor-content').clientHeight)
//     // editor.value.recreate()
//   })
// }
function changeMenuStatus(){
  if(openMenu.value){
    openMenu.value = false
  }else{
    openMenu.value = true
  }
}
function scrollNode(node: { offsetTop: number }){
  cliclMenuScroll.value = true      
  document.querySelector('.CodeMirror-scroll')!.scrollTop = node.offsetTop
  document.querySelector('.editormd-preview') && (document.querySelector('.editormd-preview')!.scrollTop = node.offsetTop)
  setTimeout(()=>{
      cliclMenuScroll.value = false
  },100)
}

function closeShortKey(){}

defineExpose({
  closeShortKey,
  saveVersionFun,
  handleSave
})

</script>
<style lang="scss" scoped>
.md-page{
  width: 100%;
  // height: 100%;
  position: relative;
  .markdown-component {
    aspect-ratio: 16/9;
    ::v-deep(.bytemd) {
      height: 100%;
    }
  }


  .editor-toolbar-mark{
    position: absolute;
    left: 0px;
    top: 0px;
    width: 100% ;
    cursor: no-drop;
    z-index: 11;
  }
  .menu-box{
    position: fixed;
    left: 0px;
    height: calc(100vh - 88px);
    top: 88px;
    max-width: 268px;
    z-index: 198;
    .menu-box-page{
        transform: translateX(-100%);
        box-shadow: 0px 6px 5px 1px rgba(54,59,76,0.15);
    }
    ::v-deep(.el-scrollbar__view){
        height: 100%;
        .el-tree{
            height: 100%;
        }
    }
  }
  .hidden-menu-box{
      transform: translateX(-100%);
  }
  .menu-button-box{
    position: fixed;
    width: 36px;
    height: 36px;
    // background: #F5F6F7;
    border-radius: 0px 6px 6px 0px;
    left: 0px;
    top: 150px;
    z-index: 199;
    box-shadow: 0px 1px 10px 0px rgba(54,59,76,0.15);
    cursor: pointer;
    .menu-icon{
        width: 36px;
        height: 36px;
        cursor: pointer;
    }
  }
  #editorPreview{
    padding: 20px 24px 16px 24px;
    max-width: 920px;
    margin: auto;
  }
}
</style>
<style lang="scss">
.md-page{
  ul{
    li{
      list-style: disc !important;
    }
  }
  ol{
    li{
      list-style: decimal !important;
    }
  }
}
</style>